/******************************************************************
 * Created by: DO HOANG HAI                                       
 * Date of Creation:
 * Date of last modification: 23rd/Sep/2007
 * Status: Finished.
 *                                                                
 * Description: Display and provide means for handling local library.                                
 * ...
 ******************************************************************/

using System;
using System.Collections.Generic;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using Pbdms.Common.DataObject;
using Pbdms.DataAccess;
using Pbdms.DataAccess.DataProvider;
using Pbdms.BusinessLogic.DataController;

namespace Pbdms.Forms.Views
{
    public partial class FrmLibrary : Form
    {
        //hold data read from the library
        ArrayList arlOfItems;
        //keep track of whether it need to ask for update data into the database
        bool bNeedSaveItemInfo = false;
        bool bNeedSaveGrdvInfo = false;

        //to check if the cell has just been clicked, if so, a need to update database might be required
        //if the content of the cell is changed. set to false when first load item of a new category.
        bool cellContentClicked = false;
        bool categoryChanged = false;

        int currentSelectedItemIndex = 0;
        int currentSelectedCategoryIndex = 0;

        //
        FileInfo curFileInfoObj = null;
        Comment curCommentObj = null;

        public FrmLibrary()
        {
            InitializeComponent();
            Pbdms.Common.Global.paintBackGround(this);   
            loadCategories();
            loadInformationalCategories();
            loadItems();

        }
        protected override void OnFormClosing(FormClosingEventArgs e)
        {
            if (bNeedSaveGrdvInfo == true || bNeedSaveItemInfo == true)
            {
                int returnValue = Common.Global.showMsgThreeButtons("Would you like to save your changes before close the windows?", 'I');
                if (returnValue == Common.GUI.MsgBoxThreeButtons.DIALOG_RESULT_YES) //button Yes is clicked ->save the information
                {
                    if (bNeedSaveGrdvInfo) saveGrdvInfo();
                    if (bNeedSaveItemInfo) saveItemInfo();
                    base.OnFormClosing(e);
                }
                if (returnValue == Common.GUI.MsgBoxThreeButtons.DIALOG_RESULT_NO)
                {
                    base.OnFormClosing(e);
                }
                if (returnValue == Common.GUI.MsgBoxThreeButtons.DIALOG_RESULT_CANCEL)
                {
                    e.Cancel = true;
                }

            }
        }

        #region "load data from library"

        /// <summary>
        /// load categories from the database
        /// </summary>
        private void loadInformationalCategories()
        {
            ArrayList arl;
            arl = CategoryController.create().getListOfCategories();
            ddlCategory.Items.Clear();
            for (int i = 0; i < arl.Count; i++)
            {
                ddlCategory.Items.Add(arl[i].ToString());
            }
            ddlCategory.SelectedIndex = 0;
        }

        /// <summary>
        /// load all items to the form
        /// </summary>
        private void loadItems()
        {                        
            arlOfItems =  ItemController.create().getListOfAllItems();
            bindDataToGridView();
            
            //if the list is not null
            if (arlOfItems != null)
            {                
                //show the first item's information
                loadItemInfo((Item)arlOfItems[0]);
                //also set the current selected item in the gridview to the first item
                currentSelectedItemIndex = 0;

                //add event handlers
                openFileDlg.FileOk += new CancelEventHandler(openFileDlg_FileOk);
                openFileDlgReviewFile.FileOk+=new CancelEventHandler(openFileDlgReviewFile_FileOk);
                this.ddlCategory.SelectedIndexChanged += new System.EventHandler(this.ddlCategory_SelectedIndexChanged);
                mtbRating.TextChanged += new EventHandler(mtbRating_TextChanged);
                grdvItem.CellValueChanged += new DataGridViewCellEventHandler(grdvItem_CellValueChanged);
                this.chkBShare.CheckedChanged += new System.EventHandler(this.chkBShare_CheckedChanged);
                this.tbSummary.TextChanged += new System.EventHandler(this.tbSummary_TextChanged);
                this.tbFileLocation.TextChanged += new System.EventHandler(this.tbFileLocation_TextChanged);
                this.tbTag.TextChanged += new System.EventHandler(this.tbTag_TextChanged);
                this.grdvItem.CellClick += new System.Windows.Forms.DataGridViewCellEventHandler(this.grdvItem_CellContentClick);
                this.grdvItem.SelectionChanged += new EventHandler(grdvItem_SelectionChanged);
                this.tbPros.TextChanged += new System.EventHandler(this.tbPros_TextChanged);
                this.tbCons.TextChanged += new System.EventHandler(this.tbCons_TextChanged);
                this.tbReviewFile.TextChanged += new EventHandler(tbReviewFile_TextChanged);
                
            }
            else
            {
                //if there is no item to be displayed
                loadItemInfo(null);
            }
            
        }

        void tbReviewFile_TextChanged(object sender, EventArgs e)
        {
            if (categoryChanged == false && cellContentClicked == false)
                bNeedSaveItemInfo = true;               
        }

        void grdvItem_SelectionChanged(object sender, EventArgs e)
        {
            if (grdvItem.SelectedRows.Count != 0)
            {
                //detect whether user selects new item
                int selectedIndex = grdvItem.SelectedRows[0].Index;
                if (currentSelectedItemIndex != selectedIndex)
                {
                    //check to see if need to update changes in detailed information of the item
                    if (bNeedSaveItemInfo)
                    {
                        int returnValue = Common.Global.showMsgTwoButtons("Would you like to update your " +
                                    "changes before switch to new item?", Common.GUI.MsgBoxTwoButtons.YES_NO, 'I');
                        if (returnValue == 1) //only if the button Yes is clicked ->save the information
                        {
                            saveItemInfo();
                        }
                    }
                    //load new item information
                    loadItemInfo((Item)arlOfItems[selectedIndex]);
                    currentSelectedItemIndex = selectedIndex;
                }
                //content of the gridview has been clicked.
                cellContentClicked = false;
            }
        }

        /// <summary>
        /// clear all information about an item which was previously displayed
        /// </summary>
        private void clearItemInfo()
        {
            //clear all             
            chkBShare.Checked = false;
            ddlCategory.ResetText();
            tbSummary.Text = "";           
            tbPros.Text = "";           
            tbCons.Text = "";            
            tbTag.Text = "";
            mtbRating.ResetText();           
            tbFileLocation.Text = "";           
            lblFileSize.Text = "";
            lblFileExistence.Text = "";        
            bNeedSaveItemInfo  = false;
            chkBCopy.Checked = false;
            tbReviewFile.Text = "";
        }

        /// <summary>
        /// enable or disable controls of the Item information area
        /// </summary>
        /// <param name="enable"></param>
        private void enableItemInfo(bool enable)
        {
            ddlCategory.Enabled = enable;
            chkBShare.Enabled = enable;
            tbSummary.Enabled = enable;
            tbPros.Enabled = enable;
            tbCons.Enabled = enable;
            mtbRating.Enabled = enable;
            tbTag.Enabled = enable;
            btnBrowseFile.Enabled = enable;
            chkBCopy.Enabled = enable;
            tbFileLocation.Enabled = enable;
            btnUpdateInfo.Enabled = enable;
            tbReviewFile.Enabled = enable;
            chkBCopy.Checked = false;
        }

        /// <summary>
        /// load information of item item to be displayed
        /// also set the current Comment & FileInfo objects corresponding to the Item object
        /// </summary>
        /// <param name="itemObj"></param>
        private void loadItemInfo(Item itemObj)
        {
                     
            //check to see if the item is null
            if (itemObj != null)
            {
                //endable controls
                enableItemInfo(true);

                String itemId = itemObj.Id;
                bool bPrivate = itemObj.BPrivate;
                String cat = itemObj.Category;
                //get information form database
                curCommentObj = CommentController.create().getCommentFromDB(itemId);
                curFileInfoObj = FileInfoController.create().getFileInfoObject(itemId);

                //display information                
                chkBShare.Checked = !bPrivate;                
                ddlCategory.SelectedIndex = Common.Global.getDdlItemByStringValue(ddlCategory, cat);

                tbSummary.Text = curCommentObj.Summary;
                tbPros.Text = curCommentObj.Pros;
                tbCons.Text = curCommentObj.Cons;
                mtbRating.Text = curCommentObj.Rating.ToString();
                tbReviewFile.Text = curCommentObj.ReviewFile;
                String newTag = "";
                
                if (curCommentObj.Tags != null)
                {
                    foreach (object sTag in curCommentObj.Tags)
                    {
                        newTag = newTag + ((String)sTag).Trim() + ", ";
                    }
                    newTag = newTag.Substring(0, newTag.Length - 2);
                }
                tbTag.Text = newTag;
                if (curFileInfoObj.Location.Contains("http"))
                {
                    tbFileLocation.Text = curFileInfoObj.Location + "/" + curFileInfoObj.FileName;
                }
                else
                {
                    tbFileLocation.Text = curFileInfoObj.Location + "\\" + curFileInfoObj.FileName;
                }
                lblFileSize.Text = curFileInfoObj.Size.ToString();
                if (curFileInfoObj.Existence)
                    lblFileExistence.Text = " Yes";
                else
                    lblFileExistence.Text = " No";

                bNeedSaveItemInfo = false;
            }
            else
            {
                //clear all before display
                curFileInfoObj = null;
                curCommentObj = null;
                clearItemInfo();
                enableItemInfo(false);
            }
            
        }

        /// <summary>
        /// load categories available
        /// </summary>
        private void loadCategories()
        {
            ArrayList arl;
            arl = CategoryController.create().getListOfCategories();
            lstVwCategory.Items.Add("All");
            for (int i = 0; i < arl.Count; i++)
            {
                lstVwCategory.Items.Add(arl[i].ToString());
            }
        }

        /// <summary>
        /// bind data from the arraylist of items to the gridview, requires to build data table
        /// </summary>
        private void bindDataToGridView()
        {
            //clear all data in the grid view
            bNeedSaveItemInfo = false;
            bNeedSaveGrdvInfo = false;
            grdvItem.Columns.Clear();

            //build the data table for gridview
            DataTable dt = new DataTable();
            //add 10 columns
            for (int i = 0; i < 10; i++)
            {
                dt.Columns.Add();
            }

            int iCount = 1;
            if (arlOfItems != null)
            {
                //for each item, add one row
                foreach (Item itemObj in arlOfItems)
                {
                    ArrayList arlOfBibTexese = itemObj.BibTexes;

                    string[] itemArray = getItemArrayForDataRow(iCount, arlOfBibTexese);
                    dt.Rows.Add(itemArray);
                    //next row
                    iCount++;
                }                
            }
            grdvItem.DataSource = dt;
            customizeGridView();
            

        }

        /// <summary>
        /// prepare data for the gridview
        /// </summary>
        /// <param name="iCount"></param>
        /// <param name="arlOfBibTexese"></param>
        /// <returns></returns>
        private string[] getItemArrayForDataRow(int iCount, ArrayList arlOfBibTexese)
        {

            //itemArray describe the data row in the gridview
            string[] itemArray = new string[10];
            for (int i = 0; i < 10; i++)
            {
                itemArray[i] = "";
            }
            //first value is index number
            itemArray[0] = iCount.ToString();

            foreach (Object btStruct in arlOfBibTexese)
            {

                BibTexStruct bts = (BibTexStruct)btStruct;
                switch (bts.name)
                {
                    case "title":
                        itemArray[1] = bts.value; break;
                    case "author":
                        itemArray[2] = bts.value; break;
                    case "publisher":
                        itemArray[3] = bts.value; break;
                    case "year":
                        itemArray[4] = bts.value; break;
                    case "edition":
                        itemArray[5] = bts.value; break;
                    case "pages":
                        itemArray[6] = bts.value; break;
                    case "editor":
                        itemArray[7] = bts.value; break;
                    case "organization":
                        itemArray[8] = bts.value; break;
                    case "volume":
                        itemArray[9] = bts.value; break;
                }
            }
            return itemArray;
        }

        /// <summary>
        /// Customize columns of the gridview, header text and size of columns
        /// </summary>
        private void customizeGridView()
        {
            for (int i = 0; i < 10; i++)
            {
                switch (i)
                {
                    case 0: grdvItem.Columns[0].HeaderText = "Index"; grdvItem.Columns[0].ReadOnly = true; grdvItem.Columns[0].Width = 50; break;
                    case 1: grdvItem.Columns[1].HeaderText = "Title"; grdvItem.Columns[1].Width = 200; break;
                    case 2: grdvItem.Columns[2].HeaderText = "Author"; grdvItem.Columns[2].Width = 150; break;
                    case 3: grdvItem.Columns[3].HeaderText = "Publisher"; grdvItem.Columns[3].Width = 100; break;
                    case 4: grdvItem.Columns[4].HeaderText = "Year"; grdvItem.Columns[4].Width = 50; break;
                    case 5: grdvItem.Columns[5].HeaderText = "Edition"; grdvItem.Columns[5].Width = 50; break;
                    case 6: grdvItem.Columns[6].HeaderText = "Pages"; grdvItem.Columns[6].Width = 50; break;
                    case 7: grdvItem.Columns[7].HeaderText = "Editor"; grdvItem.Columns[7].Width = 100; break;
                    case 8: grdvItem.Columns[8].HeaderText = "Organization"; grdvItem.Columns[8].Width = 100; break;
                    case 9: grdvItem.Columns[9].HeaderText = "Volume"; grdvItem.Columns[9].Width = 50; break;

                }

            }
        }

        #endregion

        #region "event hanlders"

        /// <summary>
        /// add new item to the library, check if the form currently exists in the application
        /// if so, call it to be activated, otherwise create an instance
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnAdd_Click(object sender, EventArgs e)
        {
            bool alreadyExist = false;
            this.WindowState = FormWindowState.Normal;
            //search in the list of children of the siblings            
            foreach (Form frm in (this.MdiParent.MdiChildren))
            {
                if (frm.GetType().Equals(typeof(Pbdms.Forms.Tools.FrmAddItem)))
                {
                    frm.Activate();
                    frm.WindowState = FormWindowState.Normal;
                    alreadyExist = true;
                    break;
                }
            }
            //if doesn't exist
            if (!alreadyExist)
            {
                Pbdms.Forms.Tools.FrmAddItem frmSerach = new Pbdms.Forms.Tools.FrmAddItem();
                frmSerach.MdiParent = this.MdiParent ;
                frmSerach.Show();
            }
        }

        /// <summary>
        /// when close, check if it is neccessary to ask for saving
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void lnkClose_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            if (bNeedSaveItemInfo || bNeedSaveGrdvInfo )
            {
                int returnValue = Common.Global.showMsgThreeButtons("You've made some changes. DO you want to save information before close?", 'I');
                if (returnValue == 1)
                {
                    saveItemInfo();
                }
                else if (returnValue == -1)   //btn Cancel is clicked -> no action to be taken        
                    return;              
            }            
            this.Close(); //close the library form            
        }

       /// <summary>
       /// 
       /// </summary>
       /// <param name="sender"></param>
       /// <param name="e"></param>
        private void lstVwCategory_ItemSelectionChanged(object sender, EventArgs e)
        {
            if (lstVwCategory.SelectedItems.Count > 0)
            {
                int selectedCategoryIndex = lstVwCategory.SelectedItems[0].Index ;
                //if the selected category has been changed
                if (selectedCategoryIndex != currentSelectedCategoryIndex)
                {
                    //set the first item in the gridview as the selected item
                    currentSelectedItemIndex = 0;
                    //set the current category to the newly selected category
                    currentSelectedCategoryIndex = selectedCategoryIndex;
                    //load the category
                    loadSelectedCategory(currentSelectedCategoryIndex);
                }         
                
                
            }
        }

        /// <summary>
        /// load items according to the selected category index
        /// </summary>
        /// <param name="categoryIndex"></param>
        private void loadSelectedCategory(int categoryIndex)
        {
            cellContentClicked = false;
            if (bNeedSaveGrdvInfo || bNeedSaveItemInfo)
            {
                int returnValue = Common.Global.showMsgTwoButtons("Would you like to save your changes before switch to the new category?", Common.GUI.MsgBoxTwoButtons.YES_NO, 'I');
                if (returnValue == 1) //only if the button Yes is clicked ->save the information
                {
                    if (bNeedSaveGrdvInfo) saveGrdvInfo();
                    if (bNeedSaveItemInfo) saveItemInfo();
                }
            }

            //start changing to new category.
            String sCatName = lstVwCategory.Items[categoryIndex].Text;
            categoryChanged = true;
            if (sCatName != null)
            {
                ArrayList arlOfItems;
                if (sCatName.Equals("All"))
                {
                    arlOfItems = ItemController.create().getListOfAllItems();
                }
                else
                {
                    arlOfItems = ItemController.create().getListOfItemsByCategory(sCatName);
                }
                this.arlOfItems = arlOfItems;
                bindDataToGridView();
                if (arlOfItems != null)
                {
                    loadItemInfo((Item)arlOfItems[0]); //always load the first item in the gridview
                }
                else //clear all
                    loadItemInfo(null);
            }
            //end changing
            categoryChanged = false;
        }
      
        private void btnBrowseFile_Click(object sender, EventArgs e)
        {
            this.openFileDlg.ShowDialog();
            openFileDlg.Multiselect = false;            
        }

        private void openFileDlg_FileOk(object sender, CancelEventArgs e)
        {
            chkBCopy.Enabled = true;
            tbFileLocation.Text = openFileDlg.FileName;
            //file location is changed -> need to ask to save before exiting the window
            bNeedSaveItemInfo  = true;
        }
        private void openFileDlgReviewFile_FileOk(object sender, CancelEventArgs e)
        {   
            tbReviewFile.Text = openFileDlgReviewFile.FileName;
            //file location is changed -> need to ask to save before exiting the window
            bNeedSaveItemInfo = true;
        }
        private void grdvItem_CellContentClick(object sender, DataGridViewCellEventArgs e)
        {
            cellContentClicked = true;
        }

        ///// <summary>
        ///// call preference form and display tab Library
        ///// </summary>
        ///// <param name="sender"></param>
        ///// <param name="e"></param>
        //private void lnkLibrarySetting_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        //{
        //    bool alreadyExist = false;
        //    this.WindowState = FormWindowState.Normal;
        //    foreach (Form frm in (this.MdiParent.MdiChildren ))
        //    {
        //        if (frm.GetType().Equals(typeof(Pbdms.Forms.Application.FrmPreference)))
        //        {
        //            frm.WindowState = FormWindowState.Normal;
        //            frm.Activate();
        //            ((TabControl)(frm.Controls.Find("tabCtrl",true)[0])).SelectedIndex = 1;
        //            alreadyExist = true;
        //            break;
        //        }
        //    }
        //    if (!alreadyExist)
        //    {
        //        Pbdms.Forms.Application.FrmPreference frmPreference = new Pbdms.Forms.Application.FrmPreference();
        //        frmPreference.MdiParent = this.MdiParent;
        //        frmPreference.WindowState = FormWindowState.Normal;
        //        ((TabControl)(frmPreference.Controls.Find("tabCtrl",true)[0])).SelectedIndex = 1;
        //        frmPreference.Show();
        //    }
        //}

        private void btnUpdateInfo_Click(object sender, EventArgs e)
        {
            if (bNeedSaveItemInfo)
            {
                saveItemInfo();
                Common.Global.showMsgOneButton("Changes have been saved successfully", 'I');
            }
            else
                Common.Global.showMsgOneButton("No changes have been made to this item. Item is up to date", 'I');
        }

        private void btnRemove_Click(object sender, EventArgs e)
        {
            //check if the gridview doesn't contain any item,if so do nothing
            if (grdvItem.SelectedRows.Count != 0)
            {
                //check application's setting, if need to ask before delete
                if ((new AppSetting()).Lib_AskBeforeDelete)
                {
                    int answer = Common.Global.showMsgTwoButtons("Deleted item will no longer exists.\r\nAre you sure to delete the selected item?", Common.GUI.MsgBoxTwoButtons.YES_NO, 'W');
                    if (answer == 1) 
                        deleteItem();  
                    else
                        return;
                }
                else
                    deleteItem();
            }
        }

        private void tbSummary_TextChanged(object sender, EventArgs e)
        {
            if (categoryChanged==false && cellContentClicked==false)
                bNeedSaveItemInfo  = true;
        }

        private void tbPros_TextChanged(object sender, EventArgs e)
        {
            if (categoryChanged == false && cellContentClicked == false)
                bNeedSaveItemInfo  = true;
        }

        private void tbCons_TextChanged(object sender, EventArgs e)
        {
            if (categoryChanged == false && cellContentClicked == false)
                bNeedSaveItemInfo  = true;
        }

        private void mtbRating_TextChanged(object sender, EventArgs e)
        {
            if (curCommentObj != null)
            {
                if (!normalizeMtbRating(mtbRating.Text).Equals("0.0") && Double.Parse(normalizeMtbRating(mtbRating.Text)) > 5)
                {
                    Common.Global.showMsgOneButton("Invalid value! Rating must be in between 0 and 5", 'W');
                    mtbRating.Text = curCommentObj.Rating.ToString();
                }
                else if (!normalizeMtbRating(mtbRating.Text).Equals(curCommentObj.Rating.ToString()))
                {
                    if (categoryChanged == false && cellContentClicked == false)
                        bNeedSaveItemInfo = true;
                }

            }
            
        }

        /// <summary>
        /// normalize the text in the masked text box for rating of item to be in friendly number format
        /// </summary>
        /// <param name="s"></param>
        /// <returns></returns>
        private String normalizeMtbRating(String s)
        {
            String[] ar = s.Split('.');
            String sReturn = "";
            if (ar[0].Equals(" "))
                sReturn = "0";
            else
                sReturn = ar[0];

            if (!ar[1].Equals(""))     
                sReturn += "." + ar[1];
            return sReturn;
        }

        private void tbTag_TextChanged(object sender, EventArgs e)
        {
            if (categoryChanged == false && cellContentClicked == false)
            {
                bNeedSaveItemInfo = true;
            }
        }

        private void tbFileLocation_TextChanged(object sender, EventArgs e)
        {
            if (categoryChanged == false && cellContentClicked == false)
            {
                bNeedSaveItemInfo = true;
                chkBCopy.Enabled = true;
            }
        }

        private void ddlCategory_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (categoryChanged == false && cellContentClicked == false)
                bNeedSaveItemInfo = true;
        }

        private void chkBShare_CheckedChanged(object sender, EventArgs e)
        {
            if (categoryChanged == false && cellContentClicked == false)
                bNeedSaveItemInfo  = true;
        }

        private void grdvItem_CellValueChanged(object sender, DataGridViewCellEventArgs e)
        {
            //if changes of the cells' content are not because of change in the selected category
            if (cellContentClicked && categoryChanged == false )
                bNeedSaveGrdvInfo  = true;
            //categoryChanged = false;
        }

        private void lnkBtnRefresh_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            //check to see if the gridview is empty or not, if empty, no need to do anything
            if (grdvItem.SelectedRows.Count != 0)
            {
                loadSelectedCategory(currentSelectedCategoryIndex);
            }
        }
        
        /// <summary>
        /// update information
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnSaveChanges_Click(object sender, EventArgs e)
        {
            if (bNeedSaveGrdvInfo || bNeedSaveItemInfo)
            {
                if (bNeedSaveGrdvInfo) saveGrdvInfo();
                if (bNeedSaveItemInfo) saveItemInfo();
                Common.Global.showMsgOneButton("Changes have been successfully updated", 'I');
            }
            else
            {
                Common.Global.showMsgOneButton("No changes have been made so far", 'I');
            }
        }
        #endregion

        #region "delete, update database"

        /// <summary>
        /// save detail of an item
        /// </summary>
        private void saveItemInfo()
        {
            if (grdvItem.SelectedRows.Count != 0)
            {
                int selectedObjectIndex = int.Parse(grdvItem.SelectedRows[0].Cells[0].Value.ToString()) - 1;
                Item itemObj = (Item)arlOfItems[selectedObjectIndex];
                itemObj.Category = ddlCategory.SelectedItem.ToString();
                ItemController.create().updateItemToDB(itemObj);

                itemObj.BPrivate = !chkBShare.Checked;

                String itemId = itemObj.Id;
                Comment commentObj = CommentController.create().getCommentFromDB(itemId);
                FileInfo fileInfoObj = FileInfoController.create().getFileInfoObject(itemId);

                //start overwriting
                commentObj.Summary = tbSummary.Text;
                commentObj.Pros = tbPros.Text;
                commentObj.Cons = tbCons.Text;

                if (mtbRating.Text.Equals(" ."))
                    commentObj.Rating = 0.0;
                else
                    commentObj.Rating = Double.Parse(mtbRating.Text);

                if ((!commentObj.ReviewFile.Equals("") && !commentObj.ReviewFile.Equals(tbReviewFile.Text))
                    || commentObj.ReviewFile.Equals(""))
                {
                    if (System.IO.File.Exists(tbReviewFile.Text))
                    {
                        String reviewFile = tbReviewFile.Text;
                        Pbdms.AppSetting aSetting = new AppSetting();
                        try
                        {
                            Common.Global.copyFile(reviewFile, aSetting.LibFolder + "\\" + reviewFile.Substring(reviewFile.LastIndexOf("\\") + 1));
                            //delete old file
                            if (!commentObj.ReviewFile.Equals("") && System.IO.File.Exists(commentObj.ReviewFile))
                                System.IO.File.Delete(commentObj.ReviewFile);
                            //update new file
                            commentObj.ReviewFile = aSetting.LibFolder + "\\" + reviewFile.Substring(reviewFile.LastIndexOf("\\") + 1);
                            tbReviewFile.Text = commentObj.ReviewFile;
                        }
                        catch
                        {
                            Common.Global.showMsgOneButton("Unexpected Error, couldn't finish copying the new review file\r\n No change of review file has been made", 'I');                            
                        }
                    }
                }

                String[] arrString = tbTag.Text.Split(',');
                if (!tbTag.Text.Equals("") && arrString.Length != 0)
                {
                    commentObj.Tags = new ArrayList();
                    for (int i = 0; i < arrString.Length; i++)
                    {
                        commentObj.Tags.Add(arrString[i]);
                    }
                }

                //file information
                String fileLocation = tbFileLocation.Text;
                if (!fileLocation.Equals(""))
                {
                    //if item's file is located on internet.
                    if (fileLocation.Contains("http"))
                    {
                        fileInfoObj.Location = fileLocation.Substring(0, fileLocation.LastIndexOf("/"));
                        fileInfoObj.FileName = fileLocation.Substring(fileLocation.LastIndexOf("/") + 1);
                        fileInfoObj.Size = 0;
                        fileInfoObj.Existence = false;

                        if (chkBCopy.Checked)
                        {
                            Pbdms.AppSetting aSetting = new AppSetting();
                            try
                            {
                                Common.Global.copyFile(fileLocation, aSetting.LibFolder + "\\" + fileInfoObj.FileName);
                                fileInfoObj.Location = aSetting.LibFolder;
                                fileInfoObj.Size = (new System.IO.FileInfo(tbFileLocation.Text)).Length;
                                lblFileSize.Text = fileInfoObj.Size.ToString();
                                fileInfoObj.Existence = true;
                            }
                            catch
                            {
                                Common.Global.showMsgOneButton("Unexpected Error, couldn't finish copyding the file",'I');
                            }
                        }
                    }
                    else  //if item's file is located on local machine.
                    {
                        if (System.IO.File.Exists(fileLocation))
                        {
                            //if the file exists, store its information
                            fileInfoObj.Existence = true;
                            System.IO.FileInfo fInfo = new System.IO.FileInfo(fileLocation);
                            fileInfoObj.Location = fInfo.Directory.FullName;
                            fileInfoObj.FileName = fInfo.Name;
                            fileInfoObj.Size = fInfo.Length;

                            //check if need to copy the file to the folder
                            if (chkBCopy.Checked)
                            {
                                Pbdms.AppSetting aSetting = new AppSetting();
                                Common.Global.copyFile(fileLocation, aSetting.LibFolder + "\\" + fileInfoObj.FileName);                                
                                fileInfoObj.Location = aSetting.LibFolder;
                                fileInfoObj.Size = (new System.IO.FileInfo(tbFileLocation.Text)).Length;
                                lblFileSize.Text  = fileInfoObj.Size.ToString();
                                tbFileLocation.Text = aSetting.LibFolder + "\\" + fInfo.Name;
                            }
                        }
                    }
                }
                
                //update to database
                           
                CommentController.create().updateCommentToDB(commentObj);
                if (!fileLocation.Equals("")) 
                    FileInfoController.create().updateFileInfoToDB(fileInfoObj);                
                ItemController.create().updateItemToDB(itemObj);
            }
            bNeedSaveItemInfo = false;
        }

        /// <summary>
        /// update all information in the gridview
        /// </summary>
        private void saveGrdvInfo()
        {
            //update all item in the gridview
            DataTable dtTable = (DataTable)grdvItem.DataSource;
            for (int i = 0; i < grdvItem.Rows.Count; i++)
            {
                int itemIndex = int.Parse(grdvItem.Rows[i].Cells[0].Value.ToString()) - 1;
                Item itemObj = (Item)arlOfItems[itemIndex];
                itemObj.BibTexes = new ArrayList();
                for (int j = 1; j < grdvItem.Columns.Count; j++)
                {
                    if (!grdvItem.Rows[i].Cells[j].Value.ToString().Equals(""))
                    {
                        BibTexStruct bts = new BibTexStruct();
                        bts.name = grdvItem.Columns[j].HeaderText.ToLower();
                        bts.value = grdvItem.Rows[i].Cells[j].Value.ToString();
                        itemObj.BibTexes.Add(bts);
                    }
                }
                
                ItemController.create().updateItemToDB(itemObj);
            }
            bNeedSaveGrdvInfo = false;

            //update the current item's attributes

        }

        /// <summary>
        /// delete the selected item in the gridvew control
        /// </summary>
        private void deleteItem()
        {
            int selectedObjectIndex = int.Parse(grdvItem.SelectedRows[0].Cells[0].Value.ToString()) - 1;
            //delete all item in , comment , fileinfo which belong to this item
            BusinessLogic.ItemSynchronizer.DeleteItem(((Item)arlOfItems[selectedObjectIndex]).Id);

            arlOfItems.RemoveAt(selectedObjectIndex);
            bindDataToGridView();
            if (arlOfItems != null && arlOfItems.Count>0)
            {
                if (arlOfItems.Count == selectedObjectIndex)
                {
                    //delete the last item
                    grdvItem.CurrentCell = grdvItem.Rows[selectedObjectIndex - 1].Cells[1];
                    loadItemInfo((Item)arlOfItems[selectedObjectIndex - 1]);
                }
                else
                {
                    grdvItem.CurrentCell = grdvItem.Rows[selectedObjectIndex].Cells[1];
                    loadItemInfo((Item)arlOfItems[selectedObjectIndex]);
                }
            }
        }

        #endregion       

        /// <summary>
        /// create pdf file showing the list of items in the library
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnToPDF_Click(object sender, EventArgs e)
        {
            if (arlOfItems == null || arlOfItems.Count == 0)
            {
                Common.Global.showMsgOneButton("Failed!\r\nThere is no item in the list",'I');
                return;
            }
            try
            {
                //save as.. (file name and path)
                String filePath = "";
                saveFileDlg.DefaultExt = ".pdf";    
                
                DialogResult dlgResult = saveFileDlg.ShowDialog(this);
                if (dlgResult.Equals(DialogResult.Cancel))
                {
                    Common.Global.showMsgOneButton("You've cancelled the operation", 'I');
                    return;
                }
                else if (dlgResult.Equals(DialogResult.OK))
                {
                    filePath = saveFileDlg.FileName;
                    

                    //form the arraylist
                    ArrayList arlBibTexes = new ArrayList();
                    foreach (object obj in arlOfItems)
                    {
                        Item itemObj = (Item)obj;
                        arlBibTexes.Add(Common.Global.constructBibTex(itemObj.BibTexes));
                    }

                    //get PDF file
                    Pbdms.BusinessLogic.PDFReporter.PDFReporter.printArlOfBibTexes(arlBibTexes, filePath);
                    Common.Global.showMsgOneButton("A Pdf file, " + filePath + ", has been successfully created", 'I');
                }
            }
            catch { }
        }

        private void btnToTextFile_Click(object sender, EventArgs e)
        {
            try
            {

                //save as.. (file name and path)
                String filePath = "";
                saveFileDlg.DefaultExt = ".txt";

                DialogResult dlgResult = saveFileDlg.ShowDialog(this);
                if (dlgResult.Equals(DialogResult.Cancel))
                {
                    Common.Global.showMsgOneButton("You've cancelled the operation", 'I');
                    return;
                }
                else if (dlgResult.Equals(DialogResult.OK))
                {
                    filePath = saveFileDlg.FileName;
                    System.IO.StreamWriter fw = new System.IO.StreamWriter(filePath,false);
                    try
                    {    
                        //write the string into the file
                        int i = 1;
                        foreach (object obj in arlOfItems)
                        {
                            Item itemObj = (Item)obj;
                            fw.WriteLine(i++ + ". " + Common.Global.constructBibTex(itemObj.BibTexes));
                        }
                    }
                    catch
                    {
                        Pbdms.Common.Global.showMsgOneButton("Error while writing into the file", 'C');
                    }
                    finally
                    {
                        fw.Close();
                    }
                }
            }
            catch { }

        }

        private void btnReviewFileBrowser_Click(object sender, EventArgs e)
        {
            this.openFileDlgReviewFile.ShowDialog();
            openFileDlg.Multiselect = false;            
        }

        private void btnPrintPdfThis_Click(object sender, EventArgs e)
        {
            if (arlOfItems == null || arlOfItems.Count == 0)
            {
                Common.Global.showMsgOneButton("Failed!\r\nThere is no item in the list", 'I');
                return;
            }
            try
            {

                //save as.. (file name and path)
                String filePath = "";
                saveFileDlg.DefaultExt = ".pdf";

                DialogResult dlgResult = saveFileDlg.ShowDialog(this);
                if (dlgResult.Equals(DialogResult.Cancel))
                {
                    Common.Global.showMsgOneButton("You've cancelled the operation", 'I');
                    return;
                }
                else if (dlgResult.Equals(DialogResult.OK))
                {
                    filePath = saveFileDlg.FileName;
                    //currently selected item
                    StringBuilder sb = new StringBuilder();
                    int selectedIndex = int.Parse(grdvItem.SelectedRows[0].Cells[0].Value.ToString()) - 1;
                    Item itemObj = (Item)arlOfItems[selectedIndex];
                    FileInfo fileInfoObj = BusinessLogic.DataController.FileInfoController.create().getFileInfoObject(itemObj.Id);
                    Comment commentObj = BusinessLogic.DataController.CommentController.create().getCommentFromDB(itemObj.Id);

                    string itemBibText = Common.Global.constructBibTex(itemObj.BibTexes);
                    sb.Append(itemBibText);
                    sb.Append("\r\nCategory: " + itemObj.Category);
                    if (fileInfoObj.Existence)
                        sb.Append("\r\nHas File: Yes");
                    else
                        sb.Append("\r\nHas File: No");
                    sb.Append("\r\nFile Size: " + fileInfoObj.Size.ToString());
                    if (itemObj.BPrivate)
                        sb.Append("\r\nShared on the network: Yes");
                    else
                        sb.Append("\r\nShared on the network: No");
                    if (commentObj.Tags != null && commentObj.Tags.Count > 0)
                    {
                        sb.Append("\r\nTag: ");
                        int j = 0;
                        foreach (string strTag in commentObj.Tags)
                        {
                            if (j > 0)
                                sb.Append(", ");
                            sb.Append(strTag);
                            j++;
                        }
                    }
                    sb.Append("\r\nRating: " + commentObj.Rating.ToString());
                    sb.Append("\r\nSummary: " + commentObj.Summary);
                    sb.Append("\r\nPros: " + commentObj.Pros);
                    sb.Append("\r\nCons: " + commentObj.Cons);
                    sb.Append("\r\nReview file: " + commentObj.ReviewFile);

                    //get PDF file
                    Pbdms.BusinessLogic.PDFReporter.PDFReporter.printString(sb.ToString(), filePath);
                    Common.Global.showMsgOneButton("A Pdf file, " + filePath + ", has been successfully created", 'I');
                }
            }
            catch { }
        }

        private void btnRunFileReview_Click(object sender, EventArgs e)
        {
            if (!tbReviewFile.Equals(""))
            {
                try
                {
                    System.Diagnostics.ProcessStartInfo psi = new System.Diagnostics.ProcessStartInfo(tbReviewFile.Text);
                    psi.UseShellExecute = true;
                    System.Diagnostics.Process.Start(psi);
                }
                catch
                {
                    Common.Global.showMsgOneButton("Unable to open the file, please check the file path", 'C');
                }
            }
        }

        private void btnRunFileDoc_Click(object sender, EventArgs e)
        {
            if (!tbFileLocation.Text.Equals(""))
            {
                try
                {
                    System.Diagnostics.ProcessStartInfo psi = new System.Diagnostics.ProcessStartInfo(tbFileLocation.Text);
                    psi.UseShellExecute = true;
                    System.Diagnostics.Process.Start(psi);
                }
                catch
                {
                    Common.Global.showMsgOneButton("Unable to open the file, please check the file path", 'C');
                }
            }
        }
    }       
    
}